package com.yic.module.mes.service.report;

import cn.hutool.core.collection.CollectionUtil;
import com.yic.framework.common.util.collection.CollectionUtils;
import com.yic.framework.datapermission.core.annotation.DataPermission;
import com.yic.module.mes.service.mo.MoService;
import com.yic.module.mes.service.reportworkhours.ReportWorkHoursService;
import com.yic.module.system.enums.dict.SystemBooleanEnum;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.yic.module.mes.controller.admin.report.vo.*;
import com.yic.module.mes.dal.dataobject.report.ReportDO;
import com.yic.framework.common.pojo.PageResult;

import com.yic.module.mes.convert.report.ReportConvert;
import com.yic.module.mes.dal.mysql.report.ReportMapper;

import static com.yic.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yic.module.mes.enums.ErrorCodeConstants.*;

/**
 * 生产报工 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class ReportServiceImpl implements ReportService {

    @Resource
    private ReportMapper reportMapper;
    @Resource
    private ReportWorkHoursService reportWorkHoursService;
    @Resource
    @Lazy
    private MoService moService;

    @Resource
    @Lazy
    private Map<String, ReportTemplete> reportTempleteMap;

    @Override
    @DataPermission(enable = false)
    public void createReport(ReportCreateReqVO createReqVO) {
        if (!reportTempleteMap.containsKey(createReqVO.getReportType())) {
            throw exception(REPORT_REPORT_TYPE_ERROE);
        }
        ReportTemplete reportTemplete = reportTempleteMap.get(createReqVO.getReportType());
        reportTemplete.report(createReqVO.getMoId(), createReqVO.getMoRouteId(), createReqVO.getReportAmount(), createReqVO.getSerialNo(), createReqVO.getCooperate(), createReqVO.getEntryList());
    }

    @Override
    public Long saveReport(ReportDO reportDO) {
        //插入
        reportMapper.insert(reportDO);
        // 返回
        return reportDO.getId();
    }

    @Override
    public void updateReport(ReportUpdateReqVO updateReqVO) {
        // 校验存在
        validateReportExists(updateReqVO.getId());
        // 更新
        ReportDO updateObj = ReportConvert.INSTANCE.convert(updateReqVO);
        reportMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteReport(Long id) {
        // 校验存在
        ReportDO report = validateReportExists(id);
        // 删除工时数据
        reportWorkHoursService.deleteReportWorkHoursByReportId(id);
        // 变更生产工单状态
        moService.changeAmount(report.getMoId(), report.getMoRouteId(), report.getReportAmount().negate(), null, null, null);
        // 删除报工数据
        reportMapper.deleteById(id);
    }

    private ReportDO validateReportExists(Long id) {
        ReportDO report = reportMapper.selectById(id);
        if (report == null) {
            throw exception(REPORT_NOT_EXISTS);
        }
        return report;
    }

    @Override
    public ReportDO getReport(Long id) {
        return reportMapper.selectById(id);
    }

    @Override
    public List<ReportDO> getReportList(Collection<Long> ids) {
        return reportMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<ReportDO> getReportPage(ReportPageReqVO pageReqVO) {
        return reportMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ReportDO> getReportList(ReportExportReqVO exportReqVO) {
        return reportMapper.selectList(exportReqVO);
    }

    @Override
    @DataPermission(enable = false)
    public Map<Long, BigDecimal> getReportGroupByMoId(Long id) {
        List<ReportDO> reportDOS = reportMapper.selectByMoId(id);
        return reportDOS.stream().collect(Collectors.groupingBy(ReportDO::getMoRouteId, Collectors.mapping(ReportDO::getReportAmount, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
    }

    @Override
    public List<ReportDO> getReportByMoRouteId(Long moRouteId) {
        return reportMapper.selectByMoRouteId(moRouteId);
    }

    @Override
    public BigDecimal getCountByMoId(Long id) {
        List<ReportDO> list = reportMapper.selectByMoId(id);
        BigDecimal reportCount = BigDecimal.ZERO;
        if (CollectionUtil.isNotEmpty(list)) {
            reportCount = list.stream().map(ReportDO::getReportAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        return reportCount;
    }

    @Override
    public BigDecimal getReportAmountByMoRouteId(Long id) {
        List<ReportDO> list = reportMapper.selectByMoRouteId(id);
        BigDecimal amount = BigDecimal.ZERO;
        if (CollectionUtil.isNotEmpty(list)) {
            amount = list.stream().map(ReportDO::getReportAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        return amount;
    }

    @Override
    public ReportDO getReportBySerialNo(Long moId, Long moRouteId, String serialNo) {
        return reportMapper.selectBySerialNo(moId, moRouteId, serialNo);
    }

    @Override
    public List<ReportDO> getReportBySerialNo(String serialNo) {
        return reportMapper.selectBySerialNo(serialNo);
    }

    @Override
    public void batchUpdateReport(List<ReportDO> reportList) {
        reportMapper.batchUpdate(reportList);
    }

    @Override
    public List<ReportDO> getReportList(Long factoryId, Long workshopId, LocalDateTime[] timeArr) {
        return reportMapper.selectList(factoryId, workshopId, timeArr, SystemBooleanEnum.YES.getSystemBoolean());
    }

    @Override
    public void updateReportByErpInId(Long erpProduceInId) {
        ReportDO reportDO = new ReportDO();
        reportDO.setErpProduceInId(0L);
        reportMapper.updateByErpInId(reportDO, erpProduceInId);
    }

}
